# coding:utf8
import Queue
import time
import threading
import os
import re

import logging.config
import utils
if utils.main_is_frozen():
    logging._srcfile = r"logging\__init__.pyo"
    
import parse_config

from watch_directory import Watcher
from sync_client import SyncClient

class SyncProcess(threading.Thread):
    def __init__(self, watch_dir, sync_id, **kwargs):
        threading.Thread.__init__(self, **kwargs)
        self.watch_dir = watch_dir
        self.sync_id = sync_id
        self.filter = tuple(parse_config.parse_filter_rule())
        
    def run(self):
        LOG.info('Monitor files changing under' + self.watch_dir)
        files_changed_queue = Queue.Queue()        
        watcher = Watcher(self.watch_dir, files_changed_queue)
        watcher.start()
        
        while True:
            changed = self.check_changes(files_changed_queue)
            for (path, file) in changed:
                SyncClient(self.sync_id, path, file).start()
            time.sleep(1)
            
    def ignore_file(self, file):
        include, exclude = self.filter

        # 判断目录是不是在忽略名单里
        dir, file = os.path.split(file)
        tfile = file
        while len(tfile) > 0:
            if dir in exclude:
                LOG.info("ignore %s, in directory black-list" % file) 
                return True    
            dir, tfile = os.path.split(dir)

        # 判断文件后缀名是否在白名单里面
        ext = os.path.splitext(file)[1]
        if ext in include: return False
        LOG.info("ignore %s, not in suffix list" % file)
        return True
        
    def check_changes(self, files_changed_queue):
        changed = {}
        actions = {}
        while True:
            try:
                type, path, file, act = files_changed_queue.get_nowait()
                if self.ignore_file(file): continue
                if type == 'folder' and act == 'Updated': continue
                if file not in changed:
                    changed[file] = [type, path, act]
                    actions[file] = []
                if type != 'Deleted': changed[file][0] = type
                actions[file].append(act)
            except Queue.Empty:
                break
        
        ret = []
        if changed:
            for i in changed.keys():
                act_list = actions[i]
                if act_list[0] == 'Created' and act_list[-1] == 'Deleted':
                    #print i, 'is a tempary file, was deleted'
                    del changed[i]
                    del actions[i]
                    continue
                changed[i][2] = act_list[-1]
            
            for file, info in changed.iteritems():
                type, path, act = info
                #只做文件修改的同步，删除操作比较危险
                if act != 'Updated' or type != 'file': continue
                LOG.info(' '.join([type, file, act]))
                ret.append((path, file))
        return set(ret)


if __name__ == '__main__':
    main_dir = utils.get_main_dir()
    os.chdir(main_dir)
    config_file = os.path.join(main_dir, 'logging.conf')
    
    logging.config.fileConfig(config_file)
    LOG = logging.getLogger('sync')
    
    processing = []
    for watch, sync in parse_config.parse_watch_dir():
        t = SyncProcess(watch, sync)
        processing.append(t)
        t.start()
    
    
    while len(processing) > 0:
        dead = []
        for i in processing:
            i.join(1)
            if not i.isAlive():
                dead.append(i)
        processing = [i for i in processing if i not in dead]
        
